package org.report.excel;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.alibaba.excel.read.builder.ExcelReaderSheetBuilder;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.MapUtils;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import jakarta.servlet.http.HttpServletResponse;
import org.report.excel.dto.ExcelReadDto;
import org.report.excel.dto.ExcelWriteDto;

import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 参考文档：<a href="https://easyexcel.opensource.alibaba.com/docs/current/">...</a>
 * <a href="https://zhuanlan.zhihu.com/p/692721447">...</a>
 *
 * @author Administrator
 * @date 2024/5/20 0020 8:48
 */
public class ExcelUtils {
    public static <T> void download(HttpServletResponse response, String fileName, String sheetName, List<T> dataList) throws IOException {
        if (StringUtils.isBlank(sheetName)) {
            sheetName = "Sheet1";
        }
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8).replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream(), dataList.get(0).getClass()).autoCloseStream(Boolean.FALSE).sheet(sheetName)
                    .doWrite(dataList);
        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = MapUtils.newHashMap();
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            response.getWriter().println(JSON.toJSONString(map));
        }
    }

    public static <T> List<T> read(File excelFile, Class<T> tClass) {
        List<T> list = new ArrayList<>();
        EasyExcel.read(excelFile, defaultReadListener(list, tClass)).sheet().doRead();
        return list;
    }

    public static <T> List<T> read(ExcelReadDto<T> dto) {
        List<T> list = new ArrayList<>();
        ExcelReaderBuilder excelReaderBuilder = new ExcelReaderBuilder();
        excelReaderBuilder.registerReadListener(defaultReadListener(list, dto.getTClass()));
        if (dto.getInputStream() != null) {
            excelReaderBuilder.file(dto.getInputStream());
        } else {
            excelReaderBuilder.file(dto.getExcelFile());
        }
        ExcelReaderSheetBuilder excelReaderSheetBuilder = new ExcelReaderSheetBuilder(excelReaderBuilder.build());
        if (dto.getSheetNo() != null) {
            excelReaderSheetBuilder.sheetNo(dto.getSheetNo());
        }
        if (StringUtils.isNotBlank(dto.getSheetName())) {
            excelReaderSheetBuilder.sheetName(dto.getSheetName());
        }
        if (dto.getHeadRowNumber() != null) {
            excelReaderSheetBuilder.headRowNumber(dto.getHeadRowNumber());
        }
        excelReaderSheetBuilder.doRead();
        return list;
    }

    public static <T> void write(ExcelWriteDto<T> dto, List<T> dataList) {
        ExcelWriterBuilder excelWriterBuilder = new ExcelWriterBuilder();
        excelWriterBuilder.head(dto.getTClass());
        if (dto.getOutputStream() != null) {
            excelWriterBuilder.file(dto.getOutputStream());
        } else if (StringUtils.isNotBlank(dto.getExcelFilePath())) {
            excelWriterBuilder.file(dto.getExcelFilePath());
        } else {
            excelWriterBuilder.file(dto.getExcelFile());
        }
        if (dto.getIncludeColumnNames() != null && dto.getIncludeColumnNames().size() > 0) {
            excelWriterBuilder.includeColumnFieldNames(dto.getIncludeColumnNames());
        }
        if (dto.getExcludeColumnNames() != null && dto.getExcludeColumnNames().size() > 0) {
            excelWriterBuilder.excludeColumnFieldNames(dto.getExcludeColumnNames());
        }
        ExcelWriterSheetBuilder excelWriterSheetBuilder = new ExcelWriterSheetBuilder(excelWriterBuilder.build());
        if (dto.getSheetNo() != null) {
            excelWriterSheetBuilder.sheetNo(dto.getSheetNo());
        } else if (StringUtils.isNotBlank(dto.getSheetName())) {
            excelWriterSheetBuilder.sheetName(dto.getSheetName());
        }
        excelWriterSheetBuilder.doWrite(dataList);
    }

    /**
     * 默认的读取监听器
     *
     * @param list   存储数据的列表
     * @param tClass 要转换的类型
     * @return ReadListener
     */
    private static <T> ReadListener defaultReadListener(List<T> list, Class<T> tClass) {
        return new ReadListener() {
            @Override
            public void invoke(Object o, AnalysisContext analysisContext) {
                list.add(JSONObject.parseObject(JSONObject.toJSONString(o), tClass));
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {

            }
        };
    }
}
